package com.wu.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wu.client.constant.RedisKeyConstant;
import com.wu.client.constant.RelationShipTypeEnum;
import com.wu.client.constant.ResTypeEnum;

import com.wu.client.dao.redis.Likes;
import com.wu.client.service.RelationshipService;
import com.wu.client.service.SongService;
import com.wu.client.service.UserLikesService;
import com.wu.client.utils.ListUtil;
import com.wu.client.utils.MinIoUtil;
import com.wu.client.utils.PageRespUtil;
import com.wu.client.vo.res.PageResp;
import com.wu.client.vo.res.album.AlbumBaseResp;
import com.wu.client.vo.res.song.SongResp;
import com.wu.constant.Enum.MinIoNameEnum;
import com.wu.mysql.entiy.AlbumDO;
import com.wu.mysql.entiy.RelationshipDO;
import com.wu.mysql.entiy.SongDO;
import com.wu.mysql.mapper.AlbumMapper;
import com.wu.mysql.mapper.RelationshipMapper;
import com.wu.mysql.mapper.SongMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class SongServiceImpl extends ServiceImpl<SongMapper, SongDO> implements SongService {
    private final RelationshipService relationshipService;
    private final AlbumMapper albumMapper;
    private final UserLikesService userLikesService;
    private final StringRedisTemplate stringRedisTemplate;
    private final MinIoUtil minIoUtil;
    @Override
    public PageResp<SongResp> getArtistSongs(Long artistId, Long userId, Integer page, Integer limit) {
        PageResp<SongResp> pageResp =new PageResp<>();
        Page<RelationshipDO> relationshipDOPage =new Page<>(page,limit);
        LambdaQueryWrapper<RelationshipDO> relationshipDOLambdaQueryWrapper =new LambdaQueryWrapper<>();
        relationshipDOLambdaQueryWrapper.eq(RelationshipDO::getRelationshipType,RelationShipTypeEnum.ARTIST_SONG.getCode())
                .eq(RelationshipDO::getSourceId,artistId);
        Page<RelationshipDO> selectPage = relationshipService.page(relationshipDOPage, relationshipDOLambdaQueryWrapper);
        List<RelationshipDO> records = selectPage.getRecords();
        if (CollectionUtil.isEmpty(records)){
            return pageResp;
        }
        List<Long> songIds = records.stream().map(RelationshipDO::getTargetId).toList();
        List<SongDO> songDOS = this.listByIds(songIds);
        List<SongResp> songRespList = BeanUtil.copyToList(songDOS, SongResp.class);
        Map<Long, Likes> likesMap = userLikesService.checkUserIfLike(ResTypeEnum.SONG, userId, songIds);
        if (CollectionUtil.isNotEmpty(likesMap)){
            for (SongResp songResp : songRespList) {
                Likes likes = likesMap.get(songResp.getId());
                if (ObjectUtil.isNotNull(likes)){
                    songResp.setIsLiked(likes.getIsLiked());
                }
            }
        }
        LambdaQueryWrapper<RelationshipDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RelationshipDO::getRelationshipType,RelationShipTypeEnum.ALBUM_SONG.getCode())
                .in(RelationshipDO::getTargetId,songIds);
        List<RelationshipDO> relationshipDOS = relationshipService.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(relationshipDOS)){
            List<Long> albumIds = relationshipDOS.stream().map(RelationshipDO::getSourceId).toList();
            List<AlbumDO> albumDOS = albumMapper.selectBatchIds(albumIds);
            Map<Long, AlbumBaseResp> albumDOMap = albumDOS.stream().collect(Collectors.toMap(AlbumDO::getId, albumDO -> BeanUtil.toBean(albumDO, AlbumBaseResp.class)));
            Map<Long, Long> collect = relationshipDOS.stream().collect(Collectors.toMap(RelationshipDO::getTargetId, RelationshipDO::getSourceId));
            for (SongResp songResp : songRespList) {
                Long albumId = collect.get(songResp.getId());
                AlbumBaseResp albumBaseResp = albumDOMap.get(albumId);
                songResp.setAlbum(albumBaseResp);
            }
        }
        return PageRespUtil.buildPageResp(page,limit,selectPage.getTotal(),songRespList);
    }

    @Override
    public PageResp<SongResp> getUserFavoritesSongs(Long userId, Integer page, Integer limit) {
        String userLikesRedisKey = RedisKeyConstant.getUserLikesRedisKey(ResTypeEnum.SONG.getCode(), userId);
        Set<String> songIds = stringRedisTemplate.opsForSet().members(userLikesRedisKey);
        if (CollectionUtil.isNotEmpty(songIds)){
            List<Long> ids = songIds.stream().map(Long::parseLong).toList();
            long count  = ids.size();
            ids = ListUtil.subListInPage(ids, page, limit);
            List<SongDO> songDOS = this.listByIds(ids);
            if (CollectionUtil.isNotEmpty(songDOS)){
                List<SongResp> songRespList = songDOS.stream().map(songDO -> {
                    SongResp songResp = BeanUtil.toBean(songDO, SongResp.class);
                    String artisName = relationshipService.getArtisName(songDO.getId(), RelationShipTypeEnum.ARTIST_SONG);
                    songResp.setArtists(artisName);
                    String url = minIoUtil.getFileUrlDefault(MinIoNameEnum.SONG.getBucketName(), songDO.getFileName());
                    songResp.setUrl(url);
                    return songResp;
                }).toList();
            return PageRespUtil.buildPageResp(page,limit,count,songRespList);
            }

        }
        return new PageResp<>();
    }

}
